//
//  autoCompileServlet.m
//  AutoCompilerManager
//
//  Created by Vescky on 13-5-7.
//  Copyright (c) 2013年 Vescky. All rights reserved.
//

#import "autoCompileServlet.h"
#import "JSON.h"
#import "JSONKit.h"
#import "AppsJsonEngine.h"
#import "RegexKitLite.h"
#import "WorkItem.h"
#import "ReadConfig.h"
#import "FileHelper.h"
#import "AppDelegate.h"
#import "LogSystem.h"
#import "DateUtility.h"

#define AUTOCOMPILER_QUEUE_ID "AUTOCOMPILER_QUEUE"
#define BACKGROUND_SUBMITTER_QUEUE_ID "AUTOCOMPILER_QUEUE"
//#define AUTOCOMPILER_CMD_PATH @"/usr/local/autocompiler/bin/automaker"
//#define WORKSPACE_PATH [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/AutoCompilerWorkSpace"]
//#define APPID_REQUEST_INTERVAL 5 //10s内不可重复请求相同的appID
//
//#define MAX_QUEUE 5

@implementation autoCompileServlet

static autoCompileServlet *acServlet;
static dispatch_queue_t autoCompilerQueue;
static dispatch_queue_t backGroundSubmittersQueue;

NSMutableDictionary *recordList;//排队中的work的记录表
NSMutableDictionary *taskList;//执行中的task的记录列表
//NSMutableArray *abandonList;//无用的项目的记录列表
NSMutableArray *waitingList;//等待中的jobs

+ (id)shareAutoCompilerServlet {
    if (!acServlet) {
        acServlet = [[autoCompileServlet alloc] init];
        autoCompilerQueue = dispatch_queue_create(AUTOCOMPILER_QUEUE_ID, DISPATCH_QUEUE_CONCURRENT);//开启Compiler队列
        backGroundSubmittersQueue = dispatch_queue_create(BACKGROUND_SUBMITTER_QUEUE_ID, DISPATCH_QUEUE_CONCURRENT);//开启Submitter队列
        recordList = [[NSMutableDictionary alloc] init];
//        abandonList = [[NSMutableArray alloc] init];
        taskList = [[NSMutableDictionary alloc] init];
        waitingList = [[NSMutableArray alloc] init];
    }
    return acServlet;
}

- (ServletResponse *)doGet:(ServletRequest *)request {
    
    NSLog(@"=========== recieved request ============\n Path:%@ \n Headers:%@ \n Parameters:%@\n ========================================\n",request.path,request.headers,request.parameters);
    
//    [self performSelectorOnMainThread:@selector(logPath:) withObject:request.path waitUntilDone:NO];
    NSString *name = [request.parameters valueForKey:@"enName"] ? [request.parameters valueForKey:@"enName"] : @"";
    NSString *workID = [request.parameters valueForKey:@"workID"] ? [request.parameters valueForKey:@"workID"] : @"";
    
    [[LogSystem shareLogSystem] saveRecord:request.parameters forKey:workID];
    
    //获取当前排队人数的指令
    NSString *getQueueCMD = [request.parameters valueForKey:@"queue"];
    if (getQueueCMD) {
        ServletResponse *response = [[ServletResponse alloc] init];
        response.statusCode = @"200 OK";
        response.bodyString = [NSString stringWithFormat:@"%ld",[recordList count]];
        return response;
    }
    
    NSString *recoverJobs = [request.parameters valueForKey:@"recoverJobs"];
    if (recoverJobs) {
        [self loadJobList];
    }
    
    name = [self filterEnName:name];
    
    ServletResponse *response = [[ServletResponse alloc] init];
    response.statusCode = @"200 OK";
    
    NSMutableDictionary *dict = [self handleRequest:request];
    
    NSString *jsonString = [dict JSONString];
    response.bodyString = jsonString;
    NSLog(@"============= response ==============\n%@\n================================================",jsonString);
    return response;
}

- (ServletResponse *)doPost:(ServletRequest *)request {
    return [self doGet:request];
}

- (NSMutableDictionary*)handleRequest:(ServletRequest *)request {
    if (!request) {
        return nil;
    }
    
    NSString *environment = [request.parameters valueForKey:@"environment"] ? [request.parameters valueForKey:@"environment"] : @"prod";
    NSString *appID = [request.parameters valueForKey:@"appID"] ? [request.parameters valueForKey:@"appID"] : @"";
    NSString *name = [request.parameters valueForKey:@"enName"] ? [request.parameters valueForKey:@"enName"] : @"";
    NSString *workID = [request.parameters valueForKey:@"workID"] ? [request.parameters valueForKey:@"workID"] : @"";
    
    int maxConcurrent = [[ReadConfig readRawConfigByKey:@"CONCURRENT_THREAD"] intValue];
    if (maxConcurrent <= 0) {
        maxConcurrent = 3;
    }
    
    name = [self filterEnName:name];
    
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                 name,@"name",
                                 appID,@"appID",
                                 workID,@"workID",
                                 @"handling",@"status",
                                 @"Normal,compiler is working.",@"message", nil];
    
    //设置排队时间
    [dict setObject:[NSString stringWithFormat:@"%ld",([recordList count]/maxConcurrent + 1) * 5] forKey:@"queueTime"];
    
    NSString *ckResult = [self checkArgs:request];
    if ([ckResult isEqualToString:@"1"]) {
        //执行commandline调用autocompiler,开一个线程调用
        //将compile任务加入队列
        WorkItem *wItem = [[WorkItem alloc] init];
        wItem.request = request;
        wItem.date = [NSDate date];
        wItem.workID = workID;
        wItem.appID = appID;
        wItem.requestType = [request.parameters objectForKey:@"type"];
        
        //要删除的type
        if ([[request.parameters objectForKey:@"type"] isEqualToString:@"0"]) {
            //record里面存在，才会执行删除，否则
            [dict setObject:[NSString stringWithFormat:@"%ld",([recordList count]/maxConcurrent + 1) * 5] forKey:@"queueTime"];
            [dict setObject:@"done" forKey:@"status"];
            [dict setObject:[NSString stringWithFormat:@"Task for %@ has been stopped!",workID] forKey:@"message"];
            
            if ([recordList objectForKey:workID]) {
                //                if ([taskList objectForKey:workID]) {
                [self deleteJob:workID tmpPath:[NSString stringWithFormat:@"%@/%@_%@",[ReadConfig readTmpPath],environment,workID]];
                NSLog(@"Cancel job,current queue %ld",[recordList count]);
                NSString *nStr = [NSString stringWithFormat:@"%ld",[recordList count]];
                SET_WAITING_STRING(nStr);
                //                }
            }
        }
        else {//正常的type
            //队列爆满
            int maxQueue = [[ReadConfig readRawConfigByKey:@"QUEUE_MAX"] intValue];
            if ([recordList count] >= maxQueue && [environment isEqualToString:@"wip"]) {
                [dict setObject:@"OVER_MAX_QUEUE" forKey:@"queueTime"];
            }
            else {
                if (wItem) {
                    [recordList setObject:wItem forKey:workID];
                    [self saveJobList];
                }
                NSLog(@"Accept job,current queue %ld",[recordList count]);
                NSString *nStr = [NSString stringWithFormat:@"%ld",[recordList count]];
                SET_WAITING_STRING(nStr);
                //dispatch_async
                bool queue_flag = [ReadConfig readRawConfigByKey:@"QUEUE_FLAG"];
                if (queue_flag) {
                    dispatch_barrier_async(autoCompilerQueue, ^{
                        [self autocompileAction:request];
                    });
                }
                else {
                    if ([taskList count] < maxConcurrent) {
                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                            [self autocompileAction:request];
                        });
                    }
                    else {
                        if (wItem) {
                            [waitingList addObject:wItem];
                        }
                    }
                }
                
            }
        }
    }
    else {
        NSLog(@"Reject job,current queue %ld",[recordList count]);
        NSString *nStr = [NSString stringWithFormat:@"%ld",[recordList count]];
        SET_WAITING_STRING(nStr);
        
        [dict setObject:@"stopped" forKey:@"status"];
        [dict setObject:[NSString stringWithFormat:@"Error:%@",ckResult] forKey:@"message"];
        
        NSMutableDictionary *dDict = [[NSMutableDictionary alloc] init];
        [dDict setObject:[NSString stringWithFormat:@"%ld",([recordList count]/maxConcurrent + 1) * 5] forKey:@"queueTime"];
        [dDict setObject:@"0" forKey:@"status"];
        [dDict setObject:workID forKey:@"workID"];
        [dDict setObject:appID forKey:@"appID"];
        [dDict setObject:([request.parameters objectForKey:@"environment"] ? [request.parameters objectForKey:@"environment"] : @"") forKey:@"environment"];
        [dDict setObject:([request.parameters objectForKey:@"type"] ? [request.parameters objectForKey:@"type"] : @"")  forKey:@"type"];
        [dDict setObject:ckResult forKey:@"reason"];
        [dDict setObject:@"" forKey:@"ipaUrl"];
        [dDict setObject:@"" forKey:@"apkUrl"];
        [dDict setObject:request forKey:@"requestInfo"];
        
        [self submitResultInBackground:dDict];
    }
    
    return dict;
}

#pragma mark - autocompiler的调用
- (void)autocompileAction:(ServletRequest *)request {
    
    NSString *bundleName = [request.parameters valueForKey:@"enName"] ? [request.parameters valueForKey:@"enName"] : @"";
    NSString *bType = [request.parameters valueForKey:@"type"] ? [request.parameters valueForKey:@"type"] : @"1"; //0-stop,1-all,2-ios,3-android
    NSString *bEnvironment = [request.parameters valueForKey:@"environment"] ? [request.parameters valueForKey:@"environment"] : @"prod";
    NSString *workID = [request.parameters objectForKey:@"workID"];
    NSString *zipUrl = [request.parameters valueForKey:@"zipUrl"] ? [request.parameters valueForKey:@"zipUrl"] : @"";
    NSString *appId = [request.parameters objectForKey:@"appID"];
    bool noBuild = NO;
    if ([request.parameters objectForKey:@"noBuild"]) {
        noBuild = YES;
    }
    
    NSString *typeStr = @"all";
    if ([bType isEqualToString:@"2"]) {
        typeStr = @"ios";
    }
    else if ([bType isEqualToString:@"3"]) {
        typeStr = @"android";
    }
    NSString *tmpPathForCurrentJob = [NSString stringWithFormat:@"%@/%@_%@_%@",[ReadConfig readTmpPath],bEnvironment,appId,typeStr];//tmp中项目的位置
    
    NSFileManager *fm = [NSFileManager defaultManager];
    
    NSLog(@">>>>>> task:%@ Begin!!!",workID);
    
    //过滤非法字符
    bundleName = [self filterEnName:bundleName];
    
    NSString *typeValue = @"";
    if ([bType isEqualToString:@"1"]) {
        typeValue = [NSString stringWithFormat:@"-ios -android"];
    }
    else if([bType isEqualToString:@"2"]){
        typeValue = [NSString stringWithFormat:@"-ios"];
    }
    else {
        typeValue = [NSString stringWithFormat:@"-android"];
    }
    
    bool isProd = YES;
    if ([bEnvironment isEqualToString:@"wip"]) {
        isProd = NO;
    }
    
    if ([fm fileExistsAtPath:tmpPathForCurrentJob]) {
        [fm removeItemAtPath:tmpPathForCurrentJob error:nil];
    }
    
    //首字母转换成小写，形成驼峰形式
    if (bundleName.length > 1) {
        NSString *fEnName = [bundleName substringToIndex:1];
        fEnName = [fEnName lowercaseString];
        bundleName = [bundleName substringFromIndex:1];
        bundleName = [fEnName stringByAppendingString:bundleName];
    }
    
    NSString *zipPath = [NSString stringWithFormat:@"%@/%@",[ReadConfig readRepoZipsPathForProd:isProd],zipUrl];
    
    NSString *incomeIpStr = [self long2IP:request.requestInfo->remote_ip];
#pragma mark - pre-production start 1
    //判断是否为pre-production
    NSString *automakerEnviroment = bEnvironment;
    bool isTestMode = NO;
    if ([[ReadConfig readTestIp] stringByMatching:incomeIpStr]) {
        automakerEnviroment = [NSString stringWithFormat:@"test_%@",bEnvironment];
        isTestMode = YES;
    }
#pragma mark - pre-production End 1
    
    NSString *buildMode = [request.parameters valueForKey:@"mode"];
    if (!buildMode) {
        buildMode = @"0";
    }
    
//#pragma mark - IPS_LIMIT Start
//    if ([[ReadConfig readConfigByKey:@"IPS_FOR_US"] stringByMatching:incomeIpStr]) {
//        buildMode = [NSString stringWithFormat:@"%d",[buildMode intValue] + 100];
//    }
//#pragma mark - IPS_LIMIT End
//    NSString *amPath = [ReadConfig readAutoCompilerCMDPath];
//    if ([request.parameters valueForKey:@"mode"] ) {
//        //mode = 0 普通app，mode = 1 商圈app
//        NSString *buildMode = [request.parameters valueForKey:@"mode"];
//        NSLog(@"\n\n=====================\nBuild Mode:%@=====================\n\n",buildMode);
//        if ([buildMode isEqualToString:@"1"]) {
//            amPath = [ReadConfig readAutoCompilerCMDPathForSQ];
//        }
//        else if ([buildMode isEqualToString:@"2"]) {
//            amPath = [NSString stringWithFormat:@"%@ -mode %@",[ReadConfig readAutoCompilerCMDPathForSQ],buildMode];
//        }
//    }
    NSString *cmLine = [NSString stringWithFormat:@"%@ -enname %@ %@ -out %@ -environment %@ -zipurl %@ -mode %@ --build --save",[ReadConfig readAutoCompilerCMDPath],bundleName,typeValue,tmpPathForCurrentJob,automakerEnviroment,zipPath,buildMode];
    if (noBuild) {
        cmLine = [NSString stringWithFormat:@"%@ -enname %@ %@ -out %@ -environment %@ -zipurl %@ -mode %@ --save",[ReadConfig readAutoCompilerCMDPath],bundleName,typeValue,tmpPathForCurrentJob,automakerEnviroment,zipPath,buildMode];
    }
    
    NSString *logPath = [NSString stringWithFormat:@"%@/ManagerLog_%@.log",[ReadConfig readTmpPath],workID];
    if ([fm fileExistsAtPath:logPath]) {
        [fm removeItemAtPath:logPath error:nil];
    }
    NSLog(@"ready to execute '%@'",cmLine);
    
//    system([cmLine UTF8String]);
#pragma mark - Compile Begin
    NSMutableArray *cmdArgs = [[NSMutableArray alloc] initWithArray:[cmLine componentsSeparatedByString:@" "]];
    NSString *taskResult = [self addTask:cmdArgs jobID:workID];//此处开始执行compile动作
    if (taskResult) {
        [taskResult writeToFile:logPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    
    if ([self isJobDeleted:workID]) {
        //这个job已被删除
        NSFileManager *fm = [NSFileManager defaultManager];
        [fm removeItemAtPath:tmpPathForCurrentJob error:nil];
        if ([fm fileExistsAtPath:logPath]) {
            [fm removeItemAtPath:logPath error:nil];
        }
        [self addTaskFromWaitingQueue];
        return;
    }
    
    //执行完成，查询目录中生成文件的情况
    bool ipaExist = NO,apkExist = NO;
    NSString *apkName = @"",*ipaName= @"";
    
    NSArray *arr = [fm contentsOfDirectoryAtPath:[tmpPathForCurrentJob stringByAppendingPathComponent:@"products"] error:nil];
    for (int i = 0; i < [arr count]; i++) {
        NSString *fName = [arr objectAtIndex:i];
        NSString *dPath = [tmpPathForCurrentJob stringByAppendingPathComponent:@"products"];
        if ([[fName pathExtension] isEqualToString:@"ipa"]) {
            NSDictionary * attributes = [fm attributesOfItemAtPath:[dPath stringByAppendingPathComponent:fName] error:nil];
            // file size
            NSNumber *theFileSize;
            theFileSize = [attributes objectForKey:NSFileSize];
            if ([theFileSize integerValue] > 2000000) {
                //正常在2M以上。
                ipaExist = YES;
                ipaName = fName;
            }
        }
        if ([[fName pathExtension] isEqualToString:@"apk"]) {
            apkExist = YES;
            apkName = fName;
        }
    }
    
    //判断是否成功0
    NSString *messageString = @"1";
    if ([bType isEqualToString:@"2"]) {
        //仅ios
        if (!ipaExist) {
            messageString = @"#1201";
        }
    }
    else if ([bType isEqualToString:@"3"]) {
        //仅android
        if (!apkExist) {
            messageString = @"#1202";
        }
    }
    else {
        if (!ipaExist) {
            messageString = @"#1201";
        }
        if (!apkExist) {
            messageString = @"#1202";
        }
        if (!ipaExist && !apkExist) {
            messageString = @"#1200";
        }
    }
    
    if (noBuild) {
        messageString = @"1";
    }
    
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    if ([messageString isEqualToString:@"1"]) {
        //compile成功
        [dict setObject:@"1" forKey:@"status"];
        
        //将tmp中的目录move到repo中
        NSString *repoPathForCurrentJob = [NSString stringWithFormat:@"%@/%@",[ReadConfig readAutoCompilerProductsPath],[tmpPathForCurrentJob lastPathComponent]];
        if ([fm fileExistsAtPath:repoPathForCurrentJob]) {
            [fm removeItemAtPath:repoPathForCurrentJob error:nil];
        }
        
        NSString *outZip = [tmpPathForCurrentJob stringByAppendingPathComponent:[repoPathForCurrentJob lastPathComponent]];
        [fm createDirectoryAtPath:outZip withIntermediateDirectories:NO attributes:nil error:nil];
        [fm copyItemAtPath:[tmpPathForCurrentJob stringByAppendingPathComponent:@"products"] toPath:[outZip stringByAppendingPathComponent:@"products"] error:nil];
        NSString *zipCMD = [NSString stringWithFormat:@"cd %@\n zip -r %@.zip %@",tmpPathForCurrentJob,[repoPathForCurrentJob lastPathComponent],[repoPathForCurrentJob lastPathComponent]];
        system([zipCMD UTF8String]);
        
        
        
        //从配置文件读取ipa&apk的存放路径
        NSString *gZipPath = [NSString stringWithFormat:@"%@/%@.zip",[ReadConfig readApkAndIpaStoragePathByIP:[self long2IP:request.requestInfo->remote_ip]],[repoPathForCurrentJob lastPathComponent]];
        
        if ([fm fileExistsAtPath:gZipPath]) {
            [fm removeItemAtPath:gZipPath error:nil];
        }
        [fm moveItemAtPath:[outZip stringByAppendingString:@".zip"] toPath:gZipPath error:nil];
        [fm removeItemAtPath:outZip error:nil];
        
        [fm moveItemAtPath:tmpPathForCurrentJob toPath:repoPathForCurrentJob error:nil];
        [fm moveItemAtPath:logPath toPath:[NSString stringWithFormat:@"%@/logs/%@",repoPathForCurrentJob,[logPath lastPathComponent]] error:nil];
        
        NSString *ipaPath = @"",*apkPath = @"";
        if (ipaExist) {
            ipaPath = [NSString stringWithFormat:@"%@/products/%@",[repoPathForCurrentJob lastPathComponent],ipaName];
        }
        if (apkExist) {
            apkPath = [NSString stringWithFormat:@"%@/products/%@",[repoPathForCurrentJob lastPathComponent],apkName];
        }
        
        NSString *bMode = [request.parameters valueForKey:@"mode"];
        
        if (!bMode) {
            bMode = @"0";
        }
        if (![bEnvironment isEqualToString:@"wip"] && ([bMode intValue] % 3) != 2/*![bMode isEqualToString:@"2"] && ![bMode isEqualToString:@"5"]*/) {
            //发布版的，才zip
//            NSString *sourceCodeZipPath = [NSString stringWithFormat:@"%@/%@.zip",[ReadConfig readAutoCompilerProductsPath],[repoPathForCurrentJob lastPathComponent]];
//            if ([fm fileExistsAtPath:sourceCodeZipPath]) {
//                [fm removeItemAtPath:sourceCodeZipPath error:nil];
//            }
            NSString *sourceCodeDirName = [repoPathForCurrentJob lastPathComponent];
            NSString *zipSourceCodeCMD = [NSString stringWithFormat:@"cd %@\n rm -f %@.zip\n zip -r %@.zip %@\n",[ReadConfig readAutoCompilerProductsPath],sourceCodeDirName,sourceCodeDirName,sourceCodeDirName];
            system([zipSourceCodeCMD UTF8String]);
        }
        
        [dict setObject:ipaPath forKey:@"ipaUrl"];
        [dict setObject:apkPath forKey:@"apkUrl"];
       
        messageString = @"";
    }
    else {
        [dict setObject:@"0" forKey:@"status"];
        [dict setObject:@"" forKey:@"ipaUrl"];
        [dict setObject:@"" forKey:@"apkUrl"];
        NSString *appId = [request.parameters objectForKey:@"appID"];//一定有appId的
        NSString *errorSaveDir = [NSString stringWithFormat:@"%@/%@_%@",[ReadConfig readErrorReportsPath],getStringFromDate(@"yyyyMMddHHmmss", [NSDate date]),appId];
        //[[ReadConfig readErrorReportsPath] stringByAppendingPathComponent:appId];
        
        if ([fm fileExistsAtPath:errorSaveDir]) {
            //创建错误日志储存点
            [fm removeItemAtPath:errorSaveDir error:nil];
        }
        NSLog(@">>>>>>>>> creating dir for error logs.");
        NSError *err;
        [fm moveItemAtPath:tmpPathForCurrentJob toPath:errorSaveDir error:&err];//储存compile logs
        if (err) {
            NSLog(@"Error when move %@ to %@ \n %@",tmpPathForCurrentJob,errorSaveDir,err);
            err = nil;
        }
        
        [fm moveItemAtPath:logPath toPath:[NSString stringWithFormat:@"%@/logs/%@",errorSaveDir,[logPath lastPathComponent]] error:&err];//储存主log
        if (err) {
            NSLog(@"Error when move %@ to %@ \n %@",logPath,[NSString stringWithFormat:@"%@/%@",errorSaveDir,[logPath lastPathComponent]],err);
            err = nil;
        }
    }
    
    [dict setObject:workID forKey:@"workID"];
    [dict setObject:[request.parameters objectForKey:@"appID"] forKey:@"appID"];//检查过的，不会为空的
    [dict setObject:[request.parameters valueForKey:@"type"] ? [request.parameters valueForKey:@"type"] : @"1" forKey:@"type"];
    [dict setObject:bEnvironment forKey:@"environment"];
    [dict setObject:messageString ? messageString : @"" forKey:@"reason"];
    [dict setObject:request forKey:@"requestInfo"];
    [self submitResultInBackground:dict];
    
    //执行完后，清除相应的Trash
    [recordList removeObjectForKey:workID];
    [taskList removeObjectForKey:workID];
    [self saveJobList];
    NSLog(@">>>>>> task:%@ done!!!",workID);
    NSLog(@"Job Complete,current queue %ld",[recordList count]);
    NSString *nStr = [NSString stringWithFormat:@"%ld",[recordList count]];
    SET_WAITING_STRING(nStr);
    [self addTaskFromWaitingQueue];
}

//检查workID是否应该删除
//- (bool)isWorkIDValid:(NSString*)workID {
//    if ([abandonList objectForKey:workID]) {
//        return NO;
//    }
//    else {
//        return YES;
//    }
//}

//过滤非法字符，消除数字开头的命名
- (NSString*)filterEnName:(NSString*)enName {
    enName = [enName stringByReplacingOccurrencesOfRegex:@"[^(A-Za-z0-9)]" withString:@""];
    if (enName.length < 1) {
        enName = @"apps123";
    }
    else {
       NSString* fStr = [enName substringToIndex:1];
        if ([fStr stringByMatching:@"[0-9]"]) {
            enName = [NSString stringWithFormat:@"apps%@",enName];
        }
    }
    
    if (enName.length > 30) {
        enName = [enName substringToIndex:30];
    }
    
    return enName;
}

//检查参数
- (NSString*)checkArgs:(ServletRequest *)request {
    NSString *enName = [request.parameters valueForKey:@"enName"] ? [request.parameters valueForKey:@"enName"] : @"";
    NSString *bType = [request.parameters valueForKey:@"type"] ? [request.parameters valueForKey:@"type"] : @"1"; //1-all,2-ios,3-android
    NSString *bEnvironment = [request.parameters valueForKey:@"environment"] ? [request.parameters valueForKey:@"environment"] : @"prod";
    NSString *zipUrl = [request.parameters valueForKey:@"zipUrl"] ? [request.parameters valueForKey:@"zipUrl"] : @"";
    NSString *workID = [request.parameters valueForKey:@"workID"] ? [request.parameters valueForKey:@"workID"] : @"";
    NSString *appID = [request.parameters valueForKey:@"appID"] ? [request.parameters valueForKey:@"appID"] : @"";
    
    enName = [enName lowercaseString];
    bType = [bType lowercaseString];
    bEnvironment = [bEnvironment lowercaseString];
    
    //检查是否为空
    if (!enName || enName.length < 1) {
        return @"#1000";
    }
    if (!zipUrl || zipUrl.length < 1) {
        return @"#1001";
    }
    if (!appID || appID.length < 1) {
        return @"#1002";
    }
    if (!workID || workID.length < 1) {
        return @"#1003";
    }
    
    //检查enName合法性
    if ([[enName lowercaseString] isEqualToString:@"null"] || enName.length < 1) {
        return @"#1100";
    }
    
//    if ([enName stringByMatching:@"^[A-Za-z0-9]+$"]) {
//        //只有字母和数字的组合
//        NSString *str1 = [enName substringToIndex:1];
//        if (![str1 stringByMatching:@"^[A-Za-z]+$"]) {
//            return @"#1100";
//        }
//    }
//    else {
//        return @"#1100";
//    }
    
    //检查type合法性
    if (![bType isEqualToString:@"0"] && ![bType isEqualToString:@"1"] && ![bType isEqualToString:@"2"] && ![bType isEqualToString:@"3"]) {
        return @"#1102";
    }
    
    //检查environment合法性
    if (![bEnvironment isEqualToString:@"wip"] && ![bEnvironment isEqualToString:@"prod"]) {
        return @"#1103";
    }
    
    //检查zipUrl合法性
//    if ([zipUrl stringByMatching:@"http://"]) {
//       NSURL *url1 = [NSURL URLWithString:zipUrl];
//        if (!url1) {
//            return @"#1101";
//        }
//    }
//    else {
//         return @"#1101";
//    }
    
    //检查#13xxx的错误,type=0说明是要清除的，不检查重复错误
    if ([recordList count] > 0 && ![bType isEqualToString:@"0"]) {
        //检查workID
        if ([recordList objectForKey:workID]) {
//            return @"#1300";
            //不检查重复workid
            [self deleteJob:workID tmpPath:[NSString stringWithFormat:@"%@/%@_%@",[ReadConfig readTmpPath],bEnvironment,workID]];//重复的直接删除之前的
        }
        
        //线程锁
        @synchronized(recordList) {
            //检查appID
            NSEnumerator *enumerator = [recordList keyEnumerator];
            for (NSString *str in enumerator) {
            WorkItem *wItem = [recordList objectForKey:str];
            if ([wItem.appID isEqualToString:appID]) {
                NSDate *nDate = [NSDate date];
                int aInterval = [[ReadConfig readRawConfigByKey:@"APPID_REQUEST_INTERVAL"] intValue];
                if ([nDate timeIntervalSinceDate:wItem.date] <= aInterval && [wItem.requestType isEqualToString:bType]) {
                    return @"#1302";
                }
            }
        }
        }
    }
    
    return @"1";
}

- (void)submitResultInBackground:(NSMutableDictionary*)rDict {
//    dispatch_queue_t queue1 = dispatch_queue_create("SubmitInBackground", NULL);
    dispatch_async(backGroundSubmittersQueue, ^{
        [self submitResult:rDict];
    });
}

//返回处理结果
//http://192.168.1.107/AppsPortlet/servlet/AutoComplier?state=1&projectId=402881903d3daa5d013d3f0592bd016b&ipaUrl=http://itunes.apple.com&apkUrl=http://m.apps123.apk
- (void)submitResult:(NSMutableDictionary*)dict {
    
    int submitCounter = 0;
    if ([dict objectForKey:@"AutoCompilerSubmitCounter"]) {
          submitCounter = [[dict objectForKey:@"AutoCompilerSubmitCounter"] intValue];
    }
    submitCounter++;
    [dict setObject:[NSString stringWithFormat:@"%d",submitCounter] forKey:@"AutoCompilerSubmitCounter"];
    
    NSString *urlString = [self getRequestLink:dict];
    printf("\n=======================================================================================================================================\n");
    printf("VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV\n");
    NSLog(@"\nsubmit link:%@\n",urlString);
    
    NSURL    *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSError *error = nil;
    NSData   *data = [NSURLConnection sendSynchronousRequest:request
                                           returningResponse:nil
                                                       error:&error];
    bool isSubmitFailed = YES;
    if (data) {
        NSString *rString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if ([rString stringByMatching:@"success"]) {
            isSubmitFailed = NO;
        }
    }
    if (isSubmitFailed) {
        NSLog(@"submit result failed!!\n %@",dict);
        int maxRetryTimes = [[ReadConfig readConfigByKey:@"CALL_FAIL_RETRY_TIMES_MAX"] intValue];
        if (maxRetryTimes <= 0) {
            maxRetryTimes = 3;//默认3次
        }
        if (submitCounter <= maxRetryTimes) {
            int resubmitInterval = [[ReadConfig readConfigByKey:@"CALL_FAIL_SLEEP_SECONDS"] intValue];
            if (resubmitInterval <= 0) {
                resubmitInterval = 10;
            }
            [dict setObject:urlString forKey:@"resubmitLink"];
            [dict removeObjectForKey:@"requestInfo"];//requestinfo已为空,移除
            NSLog(@"resubmit later...");
            printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
            printf("=======================================================================================================================================\n");
            [NSThread sleepForTimeInterval:resubmitInterval];
            [self submitResult:dict];
        }
        else {
            NSLog(@"\n\n >>>>>>> ReTry Over MAX TIMES!!! <<<<<<< \n\n");
            printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
            printf("=======================================================================================================================================\n");
        }
    }
    else {
        NSLog(@"result:%@  ---- Submit result success!! \n submit content:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],dict);
        printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
        printf("=======================================================================================================================================\n");
    }
    
    
    
    
//    __block NSMutableDictionary *pDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
//    __block int submitCounter = 0;
//    if ([pDict objectForKey:@"AutoCompilerSubmitCounter"]) {
//        submitCounter = [[pDict objectForKey:@"AutoCompilerSubmitCounter"] intValue];
//    }
//    submitCounter++;
//    [pDict setObject:[NSString stringWithFormat:@"%d",submitCounter] forKey:@"AutoCompilerSubmitCounter"];
//    
//    NSLog(@">>>> Submitting result... <<<<");
//    [[AppsJsonEngine sharedEngine] submitRequest:@"AutoComplier" params:dict onCompletion: ^(id jsonResponse){
//        NSLog(@"submit result success!!\n %@",pDict);
//    } onError:^(NSError *error){
//        NSLog(@"submit result failed!!\n %@",pDict);
//        if (submitCounter <= 3) {
//            NSLog(@"resubmit later...");
//            [NSThread sleepForTimeInterval:10.0];
//            [self submitResult:pDict];
//        }
//    } method:@"GET"];
    
}

- (NSString*)getRequestLink:(NSMutableDictionary*)dict {
    
    NSString *backCallIp = SERVERIP_FOR_MP;
    
#ifdef FLEXI_IP
    if ([dict objectForKey:@"resubmitLink"]) {
        return [dict objectForKey:@"resubmitLink"];
    }
    ServletRequest *sRequest = [dict objectForKey:@"requestInfo"];
    if ([sRequest respondsToSelector:@selector(extractParametersFrom:)]) {
        [dict removeObjectForKey:@"requestInfo"];
        NSString *ipStr = [self long2IP:sRequest.requestInfo->remote_ip];
        ipStr = [NSString stringWithFormat:@"http://%@/AppsPortlet/servlet/AutoComplier",ipStr];
        if (![ipStr isEqualToString:backCallIp]) {
            backCallIp = ipStr;
        }
    }
#endif
    NSString *argStr = @"";
    int i = 1;
    for (NSString *key in dict) {
        argStr = [argStr stringByAppendingFormat:@"%@=%@",key,[dict objectForKey:key]];
        if (i < [dict count]) {
            argStr = [argStr stringByAppendingString:@"&"];
        }
    }
    NSString *totalLink = [NSString stringWithFormat:@"%@?%@",backCallIp,argStr];
    totalLink = [totalLink stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return totalLink;
}

- (bool)deleteJob:(NSString*)jobId tmpPath:(NSString*)tmpPath {
    
    NSTask *task = [taskList objectForKey:jobId];
    if (task) {
        [taskList removeObjectForKey:jobId];
        [task terminate];//停止任务
        [NSThread sleepForTimeInterval:5.0];
    }
    
    [waitingList removeObject:[recordList objectForKey:jobId]];
    [recordList removeObjectForKey:jobId];
    [self saveJobList];
    
    return NO;
}


//同步下载，非异步操作
- (bool)synDownload:(NSString*)urlString saveAtPath:(NSString*)zipPath {
    NSURL    *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSError *error = nil;
    NSData   *data = [NSURLConnection sendSynchronousRequest:request
                                           returningResponse:nil
                                                       error:&error];
    
    //首先清空目录
//    NSString *zpPath = [zipPath stringByDeletingLastPathComponent];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:zipPath]) {
        [fm removeItemAtPath:zipPath error:nil];
    }
    
    if (data != nil){
        NSLog(@"下载成功");
        if ([data writeToFile:zipPath atomically:YES]) {
            NSLog(@"保存成功.");
            return YES;
        }
        else
        {
            NSLog(@"保存失败.");
            return NO;
        }

    } else {
        NSLog(@"%@", error);
        return NO;
    }
}

int mysystem(const char* cmdstring,const char* tmpfile)
{
    char cmd_string[1024];
    
    FILE *file = fopen(tmpfile, "a+");
    if (!file) {
        return -1;
    }
    fclose(file);
    
    sprintf(cmd_string, "%s > %s", cmdstring, tmpfile);
    
    return system(cmd_string);
}


- (NSString*)addTask:(NSMutableArray*)arguments jobID:(NSString*)jobID {
    if ([arguments count] < 2) {
        return nil;
    }
    //重复jobID就不添加
    if ([taskList objectForKey:jobID]) {
        return nil;
    }
    NSTask *task;
    task = [[NSTask alloc] init];
    [task setLaunchPath: [arguments objectAtIndex:0]];  //设置命令，这句话必须设置，要不可能会报出未声明得错误
    
    //第一个是位置，剩下的是参数
    [arguments removeObjectAtIndex:0];
    
    [task setArguments: arguments];  // 操作参数
    
    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];   //设置输出参数
    
    NSFileHandle *file;
    NSData *data;
    
    file = [pipe fileHandleForReading];   // 句柄
    
    [taskList setObject:task forKey:jobID];//加入列表中
    
    [task launch];  // 开始执行
    
    [task waitUntilExit];
    
//    [NSThread sleepForTimeInterval:5.0];
    
    data = [file readDataToEndOfFile];  // 读取数据
    
    NSString *string;
    string = [[NSString alloc] initWithData: data
                                   encoding: NSASCIIStringEncoding];
    return string;
   
//    NSLog (@"got\n%@", string);
}

- (bool)isJobDeleted:(NSString*)jobId {
    if ([taskList objectForKey:jobId]) {
        return NO;
    }
    return YES;
}

- (void)addTaskFromWaitingQueue {
    WorkItem *wItem;
    if ([waitingList count] > 0) {
        wItem = [waitingList objectAtIndex:0];
        [waitingList removeObjectAtIndex:0];
    }
    else {
        return;
    }
    
    int maxConcurrent = [[ReadConfig readRawConfigByKey:@"CONCURRENT_THREAD"] intValue];
    if (maxConcurrent <= 0) {
        maxConcurrent = 3;
    }
    if ([taskList count] < maxConcurrent) {
        [self autocompileAction:wItem.request];
    }
}


- (void)saveJobList {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"jobList" ofType:@"plist"];
//    NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
//    [data setObject:recordList forKey:@"recordList"];
    [recordList writeToFile:path atomically:YES];
}

- (void)loadJobList {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"jobList" ofType:@"plist"];
    NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
    NSEnumerator *enm = [data keyEnumerator];
    for (NSString *key in enm) {
        WorkItem *wItem= [data objectForKey:key];
        [self handleRequest:wItem.request];
    }
    
}

// 将10进制整数形式转换成127.0.0.1形式的ip地址
- (NSString*)long2IP:(long)longip {
    
    NSString *ipString = @"";
    ipString = [ipString stringByAppendingFormat:@"%ld.",longip >> 24];
    ipString = [ipString stringByAppendingFormat:@"%ld.",(longip & 0x00ffffff) >> 16];
    ipString = [ipString stringByAppendingFormat:@"%ld.",(longip & 0x0000ffff) >> 8];
    ipString = [ipString stringByAppendingFormat:@"%ld",longip & 0x000000ff];
    return ipString;
}


@end
